import datetime
import threading
import json
import time

from libs.utils.time_utils import TUtilsTime
from libs.comps.common.component import manager , TComponentManager , TComponent
from libs.comps.common.compDB import TCompDB
from libs.comps.common.compTDB import TCompTDB
from libs.comps.common.compKV import TCompKV
import os.path


class TIotCalcultor ( TComponent):
    def __init__(self , _manager):
        super().__init__(_manager)
        self.info ={
            "functions":{},
            "variants":{}
        }
        self.functions={
            "funMeterD01": self.funTodayPower ,
            "funMeterD02": self.funTodayPower ,
            "funMeterD03": self.funTodayPower ,
            "funMeterD04": self.funTodayPower ,
            "funMeterM01": self.funMeter ,
            "funMeterM02": self.funMeter ,
            "funMeterM03": self.funMeter ,
            "funMeterM04": self.funMeter ,
            "funMeterM05": self.funMeter ,
            "funMeterM06": self.funMeter ,
            "funMeterM07": self.funMeter ,
            "funMeterM08": self.funMeter ,
        }
    @property
    def db(self):
        res: TCompDB= None
        try:
            dbCode = self.compSettings['dbCode']
            res = self.manager.getComp("TCompDB" , dbCode)
        except Exception as er :
            self.manager.log(self , er)
        return res
    @property
    def tdb(self):
        res: TCompTDB= None
        try:
            code = self.compSettings['tdbCode']
            res = self.manager.getComp("TCompTDB" , code)
        except Exception as er :
            self.manager.log(self , er)
        return res
    @property
    def kv(self):
        res: TCompKV= None
        try:
            code = self.compSettings['compKvCode']
            res = self.manager.getComp("TCompKV" , code)
        except Exception as er :
            self.manager.log(self , er)
        return res
    def loadTasks(self):
        try:
            resVars = self.db.queryByKey("iot/calcultor/vartasks",{})
            if resVars['queryStatus']==1 :
                vars = resVars['datasetList'][0]
                taskPath = self.compSettings['taskPath']
                for var in vars:
                    dtuCode = var['dtuCode']
                    meterCode = var['meterCode']
                    varCode = var['varCode']
                    varId = var['varId']
                    funCode = var['funCode']
                    taskFn = os.path.join(taskPath , f"{funCode}/{dtuCode}/task_{meterCode}_{varCode}.json")
                    var['taskFn'] = taskFn
                    if not funCode in self.info['functions']:
                        self.info['functions'][funCode] = {
                            "vars":[]
                        }
                    self.info['variants'][varId] = var
                    self.info['functions'][funCode]['vars'].append(var)
        except Exception as er:
            self.manager.log(self , er)
    def scanTasks(self):
        try:
            for var in self.info['variants'].values():
                try:
                    taskFn = var['taskFn']
                    if os.path.exists(taskFn):
                        funCode = var['funCode']
                        if funCode in self.functions.keys():
                            funHandler = self.functions[funCode]
                            try:
                                funHandler( funCode,var )
                            except Exception as erFun:
                                self.manager.log(self , erFun)
                            try:
                                #os.remove(taskFn)
                                pass
                            except Exception as erRemoveFn:
                                self.manager.log(self , erRemoveFn)

                except Exception as err:
                    self.manager.log(self , err)

        except Exception as er:
            self.manager.log(self , er)

    def serviceHandler(self):
        try:
            super().serviceHandler()
            while self.running :
                time.sleep(1)
                self.scanTasks()
        except Exception as erBrfore:
            self.manager.log(self, erBrfore)
    def beforeStartService(self):
        try:
            super().beforeStartService()
            self.loadTasks()
        except Exception as er:
            self.manager.log(self, er)
    def startService(self):
        try:
            if not self.running:
                try:
                    self.beforeStartService()
                except Exception as erBrfore:
                    self.manager.log(self, erBrfore)
                self.serviceThread = threading.Thread(target=self.serviceHandler , daemon=True)
                self.running = True
                self.serviceThread.start()
        except Exception as er:
            self.manager.log(self, er)
    def stopService(self):
        try:
            self.running = False
        except Exception as er:
            self.manager.log(self, er)

    # 日第1次电量数据
    def getDayFirstValue(self , devCode , varCode , y , m , d  ):
        res={
            "status":0 ,
            "t":'',
            'v':0
        }
        try:
            tm0 = datetime.datetime(y,m,d)+ datetime.timedelta(hours=-8)
            startTm = tm0.strftime('%Y-%m-%dT%H:%M:%SZ')
            tm1 = tm0 + datetime.timedelta(hours=24)
            endTm = tm1.strftime('%Y-%m-%dT%H:%M:%SZ')
            sql = f"select first(v) as value  from dev_{devCode}  where vid='{varCode}' and time>='{startTm}' and time<='{endTm}'"
            queryRes = self.tdb.query(sql)
            if queryRes['status']==1 :
                values  = queryRes['result'][0][0]
                res['t'] = values['time']
                res['v'] = values['value']
                res['status'] = 1
        except Exception as er:
            print(er)
        return res
    # 统计电量
    def getPower(self , devCode , varCode , startDay:datetime.datetime , endDay:datetime.datetime  ):
        res={
            "status":0 ,
            "t0":'',
            "t1":'',
            'v':0
        }
        try:
            y0 = startDay.year
            m0 = startDay.month
            d0 = startDay.day
            endDate = startDay+datetime.timedelta(hours=24)
            y1 = endDate.year
            m1 = endDate.month
            d1 = endDate.day
            r0 = self.getDayFirstValue(devCode , varCode , y0 , m0 , d0 )
            r1 = self.getDayFirstValue(devCode , varCode , y1 , m1 , d1 )
            if r0['status']==1  and r1['status']==1:
                res['v']= r1['v'] - r0['v']
                res['t0'] = startDay.strftime('%y-%m-%d')
                res['t1'] = endDay.strftime('%y-%m-%d')
                res['status'] = 1
        except Exception as er:
            print(er)
        return res

    def funMeter(self , functionCode , varInfo):
        try:
            pass
            #print(f"call function . {functionCode}\n {varInfo}")
        except Exception as er:
            self.manager.log(self, er)
    def funTodayPower(self , functionCode , varInfo):
        try:
            varCode =''
            nowTm = datetime.datetime.now()
            if functionCode == 'funMeterD01' :
                varCode ='00010000'
            elif functionCode == 'funMeterD02' :
                varCode ='00020000'
            elif functionCode == 'funMeterD03' :
                varCode ='00030000'
            elif functionCode == 'funMeterD04' :
                varCode ='00040000'
            if varCode!='':
                devCode = varInfo['meterCode']
                startDay = datetime.datetime( nowTm.year , nowTm.month , nowTm.day)
                endDay = startDay+datetime.timedelta(hours=24)
                power = self.getPower(devCode , varCode , startDay , endDay)
                if power['status'] == 1 :
                    value = power['v']
                    tarVarCode = varInfo['varCode']
                    bucketCode = varInfo['sysCode']
                    self.kv.setValue(bucketCode , devCode , tarVarCode , value)
        except Exception as er:
            self.manager.log(self, er)

manager.registCompType("TIotCalcultor", TIotCalcultor)
